<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>ArrayBuffer</title>
		<style>
			.xyz-left-chat-line{
				width: 100%;
				font-size: 14px;
			}
			.xyz-head{
				padding: 5px;
				float: left;
			}
			.xyz-head>img{
				width: 40px;
				height: 40px;
				border: 1px solid #EEEEEE;
			}
			.xyz-chat-content{
				max-width: 70%;
				background-color: #4CD964;
				float: left;
				position: relative;
				margin-top: 10px;
				padding: 8px;
				border-radius: 5px;
			}
			
			.xyz-right-chat-line{
				width: 100%;
				font-size: 14px;
				float: right;
			}
			.xyz-right-chat-line .xyz-head{
				padding: 5px;
				float: right;
			}
			.xyz-right-chat-line .xyz-chat-content{
				padding: 8px;
				float: right;
			}
		</style>
	</head>
	<body>
		<h1>ArrayBuffer 测试</h1>
		<div style="width: 600px;height: 400px;">
			<p>聊天内容:</p>
			<div style="border: 1px solid #CCC;height: 300px;overflow: scroll; background-color: #DADADA;" id="server-msg-container">
				<div class="xyz-left-chat-line">
					<div class="xyz-head">
						<img src="image/head/head_1.jpg" />
					</div>
					<div class="xyz-chat-content" style="background-color: white;">
						<label style="margin-right: 10px;">吃饭了吗</label>
					</div>
				</div>

				<div class="xyz-right-chat-line">
					<div class="xyz-head">
						<img src="image/head/head_2.jpg" />
					</div>
					<div class="xyz-chat-content">
						<label style="margin-left: 10px;">吃了</label>
					</div>
				</div>

				<div class="xyz-right-chat-line">
					<div class="xyz-head">
						<img src="image/head/head_2.jpg" />
					</div>
					<div style="width: 70%; float: right;">
						<img src="image/bg.png" style="width: 100%; border-radius: 8px; margin-top: 10px;"/>
					</div>
				</div>
			</div>
			<p>
				<textarea id="inp-msg" style="height: 50px;width: 600px"></textarea>
				<input type="button" value="发送" id="send" style="float: right;"><br />
				选择图片： <input type="file" id="send-pic">
			</p>
		</div>
	</body>

	<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

	<script>
		// new ArrayBuffer()

		function getBytesLength(str) {
			let num = str.length; //先用num保存一下字符串的长度（可以理解为：先假设每个字符都只占用一个字节）
			for (let i = 0; i < str.length; i++) { //遍历字符串
				if (str.charCodeAt(i) > 255) { //判断某个字符是否占用两个字节，如果是，num再+1
					num++;
				}
			}
			return num; //返回最终的num，既是字符串总的字节长度
		}

		let str = 'b0223b79-7538-4ebf-9637-cb629c960ba428fd7bb4-d7b3-4df9-b743-b5d424d40fab';
		// console.log(getBytesLength(str))
	</script>
	<script>
		const authToken = "b0223b79-7538-4ebf-9637-cb629c960ba428fd7bb4-d7b3-4df9-b743-b5d424d40fab";
		console.log(new TextEncoder().encode(authToken));
		const arrayBuffer = new ArrayBuffer(84);
		const dataView = new DataView(arrayBuffer);
		// 从第0个字节开始，写一个 int 类型的数据(dataType)，占4个字节  
		dataView.setInt32(0, 123);
		dataView.setInt32(4, 54321);
		dataView.setInt32(8, 12321);
		// console.log(dataView);

		let ws = new WebSocket("ws://192.168.101.105:8088/chat");
		ws.binaryType = "arraybuffer";
		ws.onopen = function(ev) {

		};
		ws.onmessage = function(res) {
			console.info("onmessage", res);
			let inpMsg = document.getElementById("server-msg-container");
			if (typeof res.data === "string") {
				inpMsg.innerHTML += res.data + "<br/>";
			} else {
				let data = res.data;
				console.log(data)
				let flagReader = new FileReader();
				console.log(data.slice(8, 12))
				if (new DataView(data.slice(8, 12)).getInt32(0) === 1) {
					let imageReader = new FileReader();
					imageReader.readAsDataURL(data.slice(84));
					imageReader.onload = function(img) {
						let imgHtml = "<img src='" + img.target.result + "' style='width: 100px;height: 100px;'>";
						inpMsg.innerHTML += imgHtml.replace("data:application/octet-stream;", "data:image/png;") + "<br />";
					}
				} else {
					alert("后端返回的是非图片类型数据，无法显示。");
				}
			}
		};
		ws.onerror = function() {
			let inpMsg = document.getElementById("server-msg-container");
			inpMsg.innerHTML += "发生异常" + "<br/>";
		};
		ws.onclose = function() {
			let inpMsg = document.getElementById("server-msg-container");
			inpMsg.innerHTML += "webSocket 关闭" + "<br/>";
		};

		// 发送文字消息  
		document.getElementById("send").addEventListener("click", function() {
			ws.send(document.getElementById("inp-msg").value);
		}, false);

		// 发送图片  
		document.querySelector('#send-pic').addEventListener('change', function(ev) {
			let files = this.files;
			if (files && files.length) {
				let file = files[0];
				sendBinary(authToken, 10, 2, file);
			}
		}, false);

		const sendBinary = (authToken, sendUserId, receiveUserId, file) => {
			if (!sendUserId || !receiveUserId || !file) {
				return false;
			}
			const maxSize = 128940;
			if (file.size > maxSize) {
				console.log('发送的数据大小超过126KB，采用post上传');
				// 使用post上传数据
				upload(sendUserId, receiveUserId, file);
				return false;
			}
			const fileType = file.type;
			let msgType = getMsgType(fileType);
			const fileReader = new FileReader();
			fileReader.readAsArrayBuffer(file);
			fileReader.onload = function(e) {
				// 获取到文件对象  
				const fileArray = e.target.result;
				const arrayBuffer = new ArrayBuffer(12); // 创建一个12个字节的数组缓冲区  
				const dataView = new DataView(arrayBuffer);
				dataView.setInt32(0, sendUserId); // 发送者id
				dataView.setInt32(4, receiveUserId); // 接收者id
				dataView.setInt32(8, msgType); // 消息类型
				const userView = new Int8Array(dataView.buffer);
				const tokenView = new TextEncoder().encode(authToken); // 登录令牌
				const fileView = new Int8Array(fileArray); // 文件
				const sendView = concatenate(Int8Array, userView, tokenView, fileView)
				// 发送到 webSocket 服务器端  
				ws.send(sendView);
			}
		}

		const upload = (sendUserId, receiveUserId, file) => {
			const url = 'http://localhost:9090/fdfs';
			let configs = {
				headers: {
					'Content-Type': 'multipart/form-data'
				}
			};
			let form = new FormData()
			form.append('sendUserId', sendUserId);
			form.append('receiveUserId', receiveUserId);
			form.append('file', file);
			axios.post(url, form, configs)
				.then(res => {
					console.log(res)
					let data = res.data.data;
					console.log(data)
					let html = `
					<div class="xyz-right-chat-line">
						<div class="xyz-head">
							<img src="image/head/head_2.jpg" />
						</div>
						<div style="width: 70%; float: right;">
							<img src="http://192.168.3.135:22020${data}" style="width: 100%; border-radius: 8px; margin-top: 10px;"/>
						</div>
					</div>
					`;
					document.getElementById("server-msg-container")
							.insertAdjacentHTML("beforeend", html);
				})
				.catch(err => {
					console.log(err);
				})
		}

		const concatenate = (resultConstructor, ...arrays) => {
			let totalLength = 0;
			for (let arr of arrays) {
				totalLength += arr.byteLength;
			}
			let result = new resultConstructor(totalLength);
			let offset = 0;
			for (let arr of arrays) {
				result.set(arr, offset);
				offset += arr.byteLength;
			}
			return result;
		}

		const getMsgType = (fileType) => {
			let msgType = 1; // 默认图片类型
			if (!/^video/.test(fileType)) {
				msgType = 2; // 视频文件
			} else if (!/^sound/.test(fileType)) {
				msgType = 3; // 音频文件
			} else {
				msgType = 99; // 其它文件
			}
			return msgType;
		}
	</script>
</html>
